define(function(require, exports, module) {

  var PREF = "__reem__"

  var Node = require('./node')
  var Edge = require('./edge')
  var Elastic = require('./elastic')


  var _ = require('underscore')

  function Grid(el) {
    this.el = el;
    this.layout = {
      width: 1920,
      height: 1080,
      scale: 1
    };

    this.nodes = {};
    this.nodeRenderers = {}; //node渲染器池
    this.elastics = {}; //橡皮筋池

    this.edges = {};
    this.edgeRenderers = {}; //edge渲染器池

    this.textareas = {};

    if (typeof this.createNode !== 'function') {

      Grid.prototype.id = 1;

      /**
       * [createNode description]
       * @param  {[type]} opts 
       * {
       *   x:
       *   y:
       *   width:
       *   height:                      
       * }
       * @return {[type]}      [description]
       */
      Grid.prototype.createNode = function(opts) {

        var node = Node.init(this.el, Grid.prototype.id, opts);

        var elastic = new Elastic(node);

        this.nodes[Grid.prototype.id++] = node;
        return node;
      };

      Grid.prototype.bindNode = function(node, renderer) {
        if (node.id && this.nodes[node.id]) {
          this.nodeRenderers[node.id] = renderer;
        }
      }

      /**
       * [createEdge description]
       * @param  {[type]} opts
       * {
       *   source: {node:, direction:},
       *   target: {node:, direction:}
       * }
       * @return {[type]}      [description]
       */
      Grid.prototype.createEdge = function(opts) {

        var edge = Edge.init(this.el, Grid.prototype.id, opts);

        this.edges[Grid.prototype.id++] = edge;
        return edge;
      }

      Grid.prototype.bindEdge = function(edge, renderer) {
        if (edge.id && this.edges[edge.id]) {
          this.edgeRenderers[edge.id] = renderer;
        }
      }

      Grid.prototype.createTextarea = function(opts) {
        var textarea = Textarea.init(this.el, id, opts);

        this.textareas[Grid.prototype.id++] = textarea;
      }

      Grid.prototype.render = function() {
        var self = this;
        _.map(this.nodes, function(node, index) {
          self.nodeRenderers[node.id] && self.nodeRenderers[node.id].draw()
          self.textareas[node.id] && self.textareas[node.id].render()
        })

        _.map(this.edges, function(edge, index) {
          self.edgeRenderers[edge.id] && self.edgeRenderers[edge.id].draw()
          self.textareas[edge.id] && self.textareas[edge.id].render()
        })
      }
    }

  }

  return Grid
})